home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / ucrasm27.zip / SOURCE.ZIP / INSERTM.ASM < prev    next >
Assembly Source File  |  1992-06-12  |  7KB  |  316 lines

  1.  
  2. ; Need to include "lists.a" in order to get list structure definition.
  3.  
  4.         include    lists.a
  5.         extrn    sl_malloc:far
  6.  
  7.  
  8. wp        equ    <word ptr>        ;I'm a lazy typist
  9.  
  10.  
  11. ; Special case to handle MASM 6.0 vs. all other assemblers:
  12. ; If not MASM 5.1 or MASM 6.0, set the version to 5.00:
  13.  
  14.         ifndef    @version
  15. @version    equ    500
  16.         endif
  17.  
  18.  
  19.  
  20. StdGrp        group    stdlib,stddata
  21. stddata        segment    para public 'sldata'
  22. stddata        ends
  23.  
  24. stdlib        segment    para public 'slcode'
  25.         assume    cs:stdgrp
  26.  
  27.  
  28. ; sl_Insertm-    DX:SI points at a block of data bytes.
  29. ;        ES:DI points at a list.
  30. ;        CX contains a node number within the list.
  31. ;
  32. ;        This routine allocates storage for a new node on the
  33. ;        heap, copies the data from DX:SI to the new node,
  34. ;        and then links in the new node to the list before
  35. ;        the CXth node.
  36. ;
  37. ;        Returns the carry set if memory allocation error
  38. ;        occurs.
  39. ;
  40. ; Randall Hyde  3/12/92
  41. ;
  42.  
  43.         public    sl_Insertm
  44. sl_Insertm    proc    far
  45.         pushf
  46.         push    ds
  47.         push    ax
  48.         push    bx
  49.         push    cx
  50.         push    es
  51.         push    di
  52.         cld
  53.  
  54.  
  55.  
  56.         if    @version ge 600
  57.  
  58. ; MASM 6.0 version goes here
  59.  
  60. ; First, allocate storage for the new node:
  61.  
  62.         mov    ds, dx            ;Segment of target data.
  63.         mov    dx, cx            ;Save node # for later.
  64.  
  65.         mov    cx, es:[di].List.ListSize
  66.         push    cx            ;Save for later
  67.         add    cx, size NODE        ;Add in overhead
  68.         call    sl_malloc        ;Go get the memory
  69.         pop    cx            ;Get real length back.
  70.         jc    BadInsert        ;If malloc error
  71.         push    di            ;Save ptr to new NODE.
  72.  
  73. ; Compute offset to actual data area (skipping over list pointers, etc.)
  74.  
  75.         add    di, size Node
  76.  
  77.  
  78.     rep    movsb                ;Copy the node's data.
  79.         pop    si            ;Get ptr to original node
  80.         mov    cx, es            ;Make ds:si point at node.
  81.         mov    ds, cx
  82.         pop    di            ;Get ptr to list var
  83.         pop    es
  84.         push    es
  85.         push    di
  86.  
  87. ; At this point, DS:SI points at the new node on the heap and ES:DI points
  88. ; at the list variable.
  89.  
  90. ; See if the the list is empty:
  91.  
  92.         cmp    wp es:[di].List.Head+2, 0
  93.         jne    GetTheNode
  94.  
  95. ; If this is an empty list (list is empty if HEAD is NIL), then build the
  96. ; list from this single node.
  97.  
  98.         mov    wp es:[di].List.Tail, si
  99.         mov     wp es:[di].List.Head, si
  100.         mov    wp es:[di].List.CurrentNode, si
  101.         mov    wp es:[di].List.Tail+2, ds
  102.         mov    wp es:[di].List.Head+2, ds
  103.         mov    wp es:[di].List.CurrentNode+2, ds
  104.  
  105. ; Set the link fields of this new node to NIL.
  106.  
  107.         mov    wp [si].Node.Next, 0
  108.         mov    wp [si].Node.Prev, 0
  109.         mov    wp [si].Node.Next+2, 0
  110.         mov    wp [si].Node.Prev+2, 0
  111.  
  112.         pop    di
  113.         pop    es
  114.         jmp    GoodInsert
  115.  
  116.  
  117. ; If the list has some nodes, locate the CXth node down here (or locate
  118. ; the last node if there are more than CX nodes in the list).
  119.  
  120. GetTheNode:    mov    cx, dx            ;Retrieve node count.
  121.         les    di, es:[di].List.Head        ;Get ptr to first node
  122.         jmp    short IntoLoop
  123.  
  124. ; The following loop repeats until we reach the end of the list or we count
  125. ; off CX nodes in the list.
  126.  
  127. FindNode:    les    di, es:[di].Node.Next
  128. IntoLoop:    cmp    dx, wp es:[di].Node.Next
  129.         loopne    FindNode
  130.  
  131.  
  132. ;If there were items in the list, perform the insert down here.
  133.  
  134.         les    di, es:[di].List.CurrentNode    ;Get ptr to item
  135.         mov    ax, wp es:[di].Node.Prev    ;Get ptr to prev
  136.         mov    bx, wp es:[di].Node.Prev+2    ; node and save.
  137.  
  138. ; Use the address of CurrentNode as the next ptr for the new node.
  139.  
  140.         mov    wp ds:[si].Node.Next, di     ;Patch in link
  141.         mov    wp ds:[si].Node.Next+2, es
  142.  
  143. ; Okay, store the new node's address into the PREV field of the current node
  144.  
  145.         mov    wp es:[di].Node.Prev, si    ;Patch in fwd ptr
  146.         mov    wp es:[di].Node.Prev+2, ds
  147.  
  148. ; Set the PREV field of the new node to the original previous node.
  149.  
  150.         mov    wp ds:[si].Node.Prev, ax
  151.         mov    wp ds:[si].Node.Prev+2, bx
  152.  
  153. ; Set the Next field of the original previous node to point at the new
  154. ; node:
  155.  
  156.         mov    es, bx
  157.         mov    di, ax
  158.         mov    wp es:[di].Node.Next, si
  159.         mov    wp es:[di].Node.Next+2, ds
  160.  
  161. ; Set the CurrentNode ptr to the new node
  162.  
  163.         pop    di            ;Retrive ptr to list var.
  164.         pop    es
  165.         mov    wp es:[di].List.CurrentNode, si
  166.         mov    wp es:[di].List.CurrentNode+2, ds
  167.  
  168.  
  169.  
  170.  
  171.  
  172.         else
  173.  
  174. ; All other assemblers come down here:
  175.  
  176. ; First, allocate storage for the new node:
  177.  
  178.         mov    ds, dx            ;Segment of target data.
  179.         mov    dx, cx            ;Save node # for later.
  180.  
  181.         mov    cx, es:[di].ListSize
  182.         push    cx            ;Save for later
  183.         add    cx, size NODE        ;Add in overhead
  184.         call    sl_malloc        ;Go get the memory
  185.         pop    cx            ;Get real length back.
  186.         jnc    GoodIns
  187.         jmp    BadInsert        ;If malloc error
  188.  
  189. GoodIns:        push    di            ;Save ptr to new NODE.
  190.  
  191. ; Compute offset to actual data area (skipping over list pointers, etc.)
  192.  
  193.         add    di, size Node
  194.  
  195.  
  196.     rep    movsb                ;Copy the node's data.
  197.         pop    si            ;Get ptr to original node
  198.         mov    cx, es            ;Make ds:si point at node.
  199.         mov    ds, cx
  200.         pop    di            ;Get ptr to list var
  201.         pop    es
  202.         push    es
  203.         push    di
  204.  
  205. ; At this point, DS:SI points at the new node on the heap and ES:DI points
  206. ; at the list variable.
  207.  
  208. ; See if the the list is empty:
  209.  
  210.         cmp    wp es:[di].Head+2, 0
  211.         jne    GetTheNode
  212.  
  213. ; If this is an empty list (list is empty if HEAD is NIL), then build the
  214. ; list from this single node.
  215.  
  216.         mov    wp es:[di].Tail, si
  217.         mov     wp es:[di].Head, si
  218.         mov    wp es:[di].CurrentNode, si
  219.         mov    wp es:[di].Tail+2, ds
  220.         mov    wp es:[di].Head+2, ds
  221.         mov    wp es:[di].CurrentNode+2, ds
  222.  
  223. ; Set the link fields of this new node to NIL.
  224.  
  225.         mov    wp [si].Next, 0
  226.         mov    wp [si].Prev, 0
  227.         mov    wp [si].Next+2, 0
  228.         mov    wp [si].Prev+2, 0
  229.  
  230.         pop    di
  231.         pop    es
  232.         jmp    GoodInsert
  233.  
  234.  
  235. ; If the list has some nodes, locate the CXth node down here (or locate
  236. ; the last node if there are more than CX nodes in the list).
  237.  
  238. GetTheNode:    mov    cx, dx            ;Retrieve node count.
  239.         les    di, es:[di].Head        ;Get ptr to first node
  240.         jmp    short IntoLoop
  241.  
  242. ; The following loop repeats until we reach the end of the list or we count
  243. ; off CX nodes in the list.
  244.  
  245. FindNode:    les    di, es:[di].Next
  246. IntoLoop:    cmp    dx, wp es:[di].Next
  247.         loopne    FindNode
  248.  
  249.  
  250. ;If there were items in the list, perform the insert down here.
  251.  
  252.         les    di, es:[di].CurrentNode    ;Get ptr to item
  253.         mov    ax, wp es:[di].Prev    ;Get ptr to prev
  254.         mov    bx, wp es:[di].Prev+2    ; node and save.
  255.  
  256. ; Use the address of CurrentNode as the next ptr for the new node.
  257.  
  258.         mov    wp ds:[si].Next, di     ;Patch in link
  259.         mov    wp ds:[si].Next+2, es
  260.  
  261. ; Okay, store the new node's address into the PREV field of the current node
  262.  
  263.         mov    wp es:[di].Prev, si    ;Patch in fwd ptr
  264.         mov    wp es:[di].Prev+2, ds
  265.  
  266. ; Set the PREV field of the new node to the original previous node.
  267.  
  268.         mov    wp ds:[si].Prev, ax
  269.         mov    wp ds:[si].Prev+2, bx
  270.  
  271. ; Set the Next field of the original previous node to point at the new
  272. ; node:
  273.  
  274.         mov    es, bx
  275.         mov    di, ax
  276.         mov    wp es:[di].Next, si
  277.         mov    wp es:[di].Next+2, ds
  278.  
  279. ; Set the CurrentNode ptr to the new node
  280.  
  281.         pop    di            ;Retrive ptr to list var.
  282.         pop    es
  283.         mov    wp es:[di].CurrentNode, si
  284.         mov    wp es:[di].CurrentNode+2, ds
  285.  
  286.  
  287.  
  288.  
  289.  
  290.         endif
  291.  
  292. ; DANGER WILL ROBINSON! Multiple exit points.  Be wary of these if you
  293. ; change the way things are pushed on the stack.
  294.  
  295. GoodInsert:    pop    cx
  296.         pop    bx
  297.         pop    ax
  298.         pop    ds
  299.         popf
  300.         clc
  301.         ret
  302.  
  303. BadInsert:    pop    di
  304.         pop    es
  305.         pop    cx
  306.         pop    bx
  307.         pop    ax
  308.         pop    ds
  309.         popf
  310.         stc
  311.         ret
  312. sl_Insertm    endp
  313.  
  314. stdlib        ends
  315.         end
  316.